package net.hyperz.showtime.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

public class Data extends HttpLoad {
	private static Context mCtx; 
	Document mDataDoc = null;
	
	public Data(Context context) {
		mCtx = context;
	}
	
	public List<Provider> LoadProviders(String postCode) {
		
		List<Provider> providers = GetProviders(postCode);
		
		if (providers.size() <= 0) { 
			try {
				Document doc = getDocument("http://tvlistings.zap2it.com/tvlistings/ZBChooseProvider.do", 
					"method", "getProviders", 
					"zipcode", postCode);
				
				Elements providerLinks = doc.body().select("div.zc-provider-list div").select("a[href]");
				for (Element providerElem : providerLinks) {
					Provider provider = new Provider();
					String url = providerElem.attr("href");
					provider.ZapID = url.substring(url.indexOf("&lineupId=") + 10);
					provider.PostCode = postCode;
					provider.Name = providerElem.text();
					
					providers.add(provider);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if (providers.size() > 0) {
				saveProviders(providers);
			}
		}
		
		return providers;
	}
	
	public List<Network> LoadNetworks(String postCode, String zapID) {
		long providerId = GetProvider(zapID).ID;
		List<Network> networks = GetNetworks(providerId); 
		
		String listingURL = "http://tvlistings.zap2it.com/tvlistings/ZCGrid.do";
		String[] listingParameters = {"method", "decideFwdForLineup", "zipcode", postCode, 
				"setMyPreference", "false", "lineupId", zapID };
		
		if (networks.size() == 0) {
			try {
				mDataDoc = getDocument(listingURL, listingParameters);
				
				Element body = mDataDoc.body();
				Elements stationData = body.select("table.zc-row ");
				
				for (Element station : stationData) {
					Network network = new Network();
					
					network.ZapNum = station.id().replace("zc-st-", "");
					network.LogoLink = (station.select("a.zc-st-a:has(img)").size() > 0) 
						? station.select("a.zc-st-a").select("img").attr("src").toString() : "";
					network.CallSign = station.select("span.zc-st-c").select("a").html();
					network.Channel = Double.parseDouble(station.select("span.zc-st-n").select("a").html());
					byte[] bb = null; // (network.LogoLink.length() > 0) ? HttpLoad.LoadImage(network.LogoLink) : null;
					network.Logo = (bb != null) ? BitmapFactory.decodeByteArray(bb, 0, bb.length) : null;
					
					networks.add(network);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				Log.e("Data", e.getStackTrace().toString());
			}
			
			if (networks.size() > 0) {
				saveNetworks(networks, providerId);
			}
		}
		
		LoadShowData(networks, listingParameters);
		
		return networks;
	}
	
	private void LoadShowData(List<Network> networks, String... listingParams) {
		
		try {
			if (mDataDoc == null) {
				//don't load the document multiple times, we don't want to consume valuable bandwidth... 
				// rather check if there is a local temp copy saved
				
				mDataDoc = getDocument("http://tvlistings.zap2it.com/tvlistings/ZCGrid.do", listingParams);
			}
			
			Element body = mDataDoc.body();
			
			for (Network network : networks) {
				network.Shows = new ArrayList<Show>();
				
				for (Element show : body.select("table#zc-st-" + network.ZapNum).select("td.zc-pg")) {
					Show showObject = new Show();
					String details = show.attr("onclick");
					
					details = details.replace("'", "");
					details = details.substring(details.indexOf("(") + 1, details.indexOf(")"));
					String[] detailItems = details.split("[,]+");
					showObject.StartTime = Long.parseLong(detailItems[2]);
					showObject.AirTime = Long.parseLong(detailItems[3]);
					showObject.Name = show.select("a.zc-pg-t").html();
					showObject.ShowLink = show.select("a.zc-pg-t").attr("href").toString();
					showObject.Caption = show.select("span.zc-pg-e").html();
					
					network.Shows.add(showObject);
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
				
	}
	
	public List<Provider> GetProviders(String postCode) {
		List<Provider> providers = new ArrayList<Provider>();
		Provider provider = null;
		
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		Cursor cur = db.select("SELECT * FROM Provider WHERE PostCode = ?", new String[] { postCode } );
		
		if (cur.moveToFirst()) {
			do {
				provider = new Provider();
				
				provider.ID = cur.getLong(0);
				provider.PostCode = cur.getString(1);
				provider.ZapID = cur.getString(2);
				provider.Name = cur.getString(3);
				
				providers.add(provider);
			} while (cur.moveToNext());
		}
		
		db.close();
		
		return providers;
	}
	
	public Provider GetProvider(String zapId) {
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		Cursor cur = db.select("SELECT * FROM Provider WHERE ZapID = ?", new String[] { zapId } );
		Provider provider = new Provider();
		
		if (cur.moveToFirst()) {
			provider.ID = cur.getLong(0);
			provider.PostCode = cur.getString(1);
			provider.ZapID = cur.getString(2);
			provider.Name = cur.getString(3);
		}
		
		db.close();
		return provider;
	}
	
	public List<Network> GetNetworks(Long providerId) {
		List<Network> networks = new ArrayList<Network>();
		
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		Cursor cur = db.select("SELECT n.*, c.Number FROM Channel c JOIN Network n ON c.NetworkID = n.ID WHERE c.ProviderID = ?", new String[] { Long.toString(providerId) });
		
		if (cur.moveToFirst()) {
			do {
				Network network = new Network();
				
				network.ID = cur.getLong(0);
				byte[] bb = cur.getBlob(1);
				network.Logo = (bb != null) ? BitmapFactory.decodeByteArray(bb, 0, bb.length) : null;
				network.LogoLink = cur.getString(2);
				network.Name = cur.getString(3);
				network.ZapNum = cur.getString(4);
				network.CallSign = cur.getString(5);
				network.Channel = cur.getDouble(6);
				
				networks.add(network);
			} while (cur.moveToNext());
		}
		
		db.close();
		return networks;
	}
	
	public Network GetNetwork(String networkZapId, long providerId) {
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		Cursor cur = db.select("SELECT n.*, c.Number FROM Channel c JOIN Network n ON c.NetworkID = n.ID WHERE c.ProviderID = ? AND n.ZapID = ?", new String[] { Long.toString(providerId), networkZapId } );
		Network network = new Network();
		
		if (cur.moveToFirst()) {
			network.ID = cur.getLong(0);
			byte[] bb = cur.getBlob(1);
			network.Logo = (bb != null) ? BitmapFactory.decodeByteArray(bb, 0, bb.length) : null;
			network.LogoLink = cur.getString(2);
			network.Name = cur.getString(3);
			network.ZapNum = cur.getString(4);
			network.CallSign = cur.getString(5);
			network.Channel = cur.getDouble(6);
		}
		
		db.close();
		
		return network;
	}
	
	//called by method that retrieves the online data
	private void saveProviders(List<Provider> providers) {
		for (Provider provider : providers) {
			saveProvider(provider);
		}
	}
	
	public void saveProvider(Provider provider) {
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		ContentValues providerCV = new ContentValues();
		
		providerCV.put("PostCode", provider.PostCode);
		providerCV.put("ZapID", provider.ZapID);
		providerCV.put("Name", provider.Name);
		
		Cursor cur = db.select("SELECT ID FROM Provider WHERE ZapID = ?", new String[] { provider.ZapID } );
		if (cur.moveToFirst()) {
			provider.ID = cur.getLong(0);
		}
		
		if (provider.ID != 0) {
			db.update("Provider", providerCV, "ID = ?", new String[] { Long.toString(provider.ID) });
		} else {
			provider.ID = db.insert("Provider", providerCV);
		}
		
		db.close();
	}
	
	//called by method that retrieves the online data
	private void saveNetworks(List<Network> networks, long providerId) {
		for (Network network : networks) {
			saveNetwork(network, providerId);
		}
	}
	
	public void saveNetwork(Network network, long providerId) {
		DBProvider db = new DBProvider(mCtx);
		Cursor cur = null;
		long channelID = 0;
		
		db.open();
		
		ContentValues networkCV = new ContentValues();
		
		networkCV.put("Name", network.Name);
		networkCV.put("ZapID", network.ZapNum);
		networkCV.put("LogoLink", network.LogoLink);
		networkCV.put("Logo", (network.Logo != null) ? ConvertImage(network.Logo) : null);
		networkCV.put("CallSign", network.CallSign);
		
		cur = db.select("SELECT ID FROM Network WHERE ZapID = ?", new String[] { network.ZapNum } );
		
		network.ID = (cur.moveToFirst()) ? cur.getLong(0) : 0;
		
		if (network.ID != 0) {
			db.update("Network", networkCV, "ID = ?", new String[] { Long.toString(network.ID) });
		} else {
			network.ID = db.insert("Network", networkCV);
		}
		
		ContentValues channelCV = new ContentValues();
		
		channelCV.put("Number", network.Channel);
		channelCV.put("ProviderID", providerId);
		channelCV.put("NetworkID", network.ID);
		
		cur = db.select("SELECT ID FROM Channel WHERE ProviderID = ? AND NetworkID = ?", new String[] { Long.toString(providerId), Long.toString(network.ID) });
		if (cur.moveToFirst()) {
			channelID = cur.getLong(0);
		}
		
		if (channelID != 0) {
			db.update("Channel", channelCV, "ID = ?", new String[] { Long.toString(channelID) });
		} else {
			channelID = db.insert("Channel", channelCV);
		}
		
		db.close();
	}
	
	public void SaveChannel(long networkId, long providerId) {
		Element body = mDataDoc.body();
		long chanNum = Long.parseLong(body.select("span.zc-st-n").select("a").html());
		DBProvider db = new DBProvider(mCtx);
		db.open();
		
		ContentValues cv = new ContentValues();
		cv.put("Number", chanNum);
		cv.put("ProviderId", providerId);
		cv.put("NetworkId", networkId);
		
		db.insert("Channel", cv);
		
		db.close();
	}
	
	public static class Provider {
		public long ID;
		public String PostCode;
		public String ZapID;
		public String Name;
	}
	
	public static class Network {
		public Long ID;
		public String LogoLink;
		public Bitmap Logo;
		public String Name;
		public String CallSign;
		public String ZapNum;
		public double Channel;
		public List<Show> Shows;
	}
	
	public static class Show {
		public String Name;
		public Long StartTime;
		public Long AirTime;
		public String Caption;
		public String ShowLink;
	}
}
